#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QtDebug"
#include <QTimer>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>

//全局变量
long RXD_count=0;
long TXD_count=0;
bool isSend=true;
int Hex_BiaoZhi=0;
QString take;


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{

  m_pTimer = new QTimer(this);
  ui->setupUi(this);
  //程序开始默认刷新
  on_pushButton_clicked();
  //绑定收到数据的槽函数
  connect(&m_serialPort, &QSerialPort::readyRead, this, &MainWindow::readData);
  //绑定定时器超时的槽函数
  connect(m_pTimer, SIGNAL(timeout()), this, SLOT(handleTimeout()));

  //设置两个单选框为两个指示灯,并修改颜色
    ui->LED_RXD->setStyleSheet("QCheckBox{spacing:22px;color:green;}"
                                "QCheckBox::indicator:unchecked{image:url(:/Images/0);}"
                                "QCheckBox::indicator:checked{image:url(:/Images/1);}"
                                );
    ui->LED_TXD->setStyleSheet("QCheckBox{spacing:22px;color:red;}"
                                "QCheckBox::indicator:unchecked{image:url(:/Images/0);}"
                                "QCheckBox::indicator:checked{image:url(:/Images/2);}"
                                );


}

MainWindow::~MainWindow()
{
    delete ui;
}

//*****************************//
//不占用线程的延时函数
//*****************************//
void MainWindow::Delay(int msec)
{
  QTime dieTime = QTime::currentTime().addMSecs(msec);
  while( QTime::currentTime() < dieTime )
    QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

//*****************************//
//扫描可用串口,并加入到下拉框里面
//*****************************//
void MainWindow::scanSerial()
{
  qDebug()<<tr("扫描存在的串口");
  ui->XLK_ComPort->clear();
  ui->XLK_ComPort->clear();
  ui->JDT->reset();
  ui->JDT->setValue(20);
  ui->XLK_ComPort->clear();

  foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()){
    qDebug() << "Name        : " << info.portName();
    qDebug() << "Description : " << info.description();
    qDebug() << "Manufacturer: " << info.manufacturer();
    qDebug() << "isBusy(): " << info.isBusy();
    ui->XLK_ComName->addItem(info.portName());
    ui->XLK_ComPort->addItem(info.description());
  }
  ui->JDT->setValue(100);
}

//*****************************//
//装载数据函数,装载波特率等,和默认禁用的按钮
//*****************************//
void MainWindow::XLK_DataLoad()
{
  //加载波特率
  ui->XLK_BaudRate->addItem(QStringLiteral("1200"),1200);
  ui->XLK_BaudRate->addItem(QStringLiteral("2400"),2400);
  ui->XLK_BaudRate->addItem(QStringLiteral("4800"),4800);
  ui->XLK_BaudRate->addItem(QStringLiteral("9600"),9600);
  ui->XLK_BaudRate->addItem(QStringLiteral("14400"),14400);
  ui->XLK_BaudRate->addItem(QStringLiteral("19200"),19200);
  ui->XLK_BaudRate->addItem(QStringLiteral("38400"),38400);
  ui->XLK_BaudRate->addItem(QStringLiteral("43000"),43000);
  ui->XLK_BaudRate->addItem(QStringLiteral("57600"),57600);
  ui->XLK_BaudRate->addItem(QStringLiteral("76800"),76800);
  ui->XLK_BaudRate->addItem(QStringLiteral("115200"),115200);
  ui->XLK_BaudRate->addItem(QStringLiteral("128000"),128000);
  ui->XLK_BaudRate->addItem(QStringLiteral("230400"),230400);
  ui->XLK_BaudRate->addItem(QStringLiteral("256000"),256000);
  ui->XLK_BaudRate->addItem(QStringLiteral("460800"),460800);
  ui->XLK_BaudRate->addItem(QStringLiteral("921600"),921600);
  ui->XLK_BaudRate->addItem(QStringLiteral("1000000"),1000000);
  ui->XLK_BaudRate->addItem(QStringLiteral("1382400"),1382400);
  ui->XLK_BaudRate->addItem(QStringLiteral("2000000"),2000000);
  ui->XLK_BaudRate->setCurrentIndex(18);
  //停止位装载
  ui->XLK_StopBit->addItem(QStringLiteral("1位"), QSerialPort::OneStop);
  ui->XLK_StopBit->addItem(QStringLiteral("1.5位"), QSerialPort::OneAndHalfStop);
  ui->XLK_StopBit->addItem(QStringLiteral("2位"), QSerialPort::TwoStop);

  //数据位装载
  ui->XLK_DataBit->addItem(QStringLiteral("5位"), QSerialPort::Data5);
  ui->XLK_DataBit->addItem(QStringLiteral("6位"), QSerialPort::Data6);
  ui->XLK_DataBit->addItem(QStringLiteral("7位"), QSerialPort::Data7);
  ui->XLK_DataBit->addItem(QStringLiteral("8位"), QSerialPort::Data8);
  ui->XLK_DataBit->setCurrentIndex(3);

  //校验位装载
  ui->XLK_CheckBit->addItem(tr("无校验(None)"), QSerialPort::NoParity);
  ui->XLK_CheckBit->addItem(tr("偶校验(Even)"), QSerialPort::EvenParity);
  ui->XLK_CheckBit->addItem(tr("奇校验(Odd)"), QSerialPort::OddParity);
  ui->XLK_CheckBit->addItem(tr("标记校验(Mark)"), QSerialPort::MarkParity);
  ui->XLK_CheckBit->addItem(tr("空间校验(Space)"), QSerialPort::SpaceParity);
  //流控位装载
  ui->XLK_flowBit->addItem(tr("无控制流(None)"), QSerialPort::NoFlowControl);
  ui->XLK_flowBit->addItem(tr("硬件控制流(RTS/CTS)"), QSerialPort::HardwareControl);
  ui->XLK_flowBit->addItem(tr("软件控制流(XON/XOFF)"), QSerialPort::SoftwareControl);

  //禁用发送按钮
  ui->AN_Send->setEnabled(false);
  ui->AN_SendFile->setEnabled(false);
  ui->AN_SendItem->setEnabled(false);
  ui->AN_SendArray->setEnabled(false);
  ui->AN_StopSend->setEnabled(false);
  ui->XZK_TimerSend->setEnabled(false);

  //设置窗口标题
  this->setWindowTitle("串口关闭");
}

//*****************************//
//刷新串口按钮被按下槽函数
//*****************************//
void MainWindow::on_pushButton_clicked()
{
  scanSerial();
  XLK_DataLoad();
  ui->XLK_ComName->setCurrentIndex(1);
  ui->XLK_ComPort->setCurrentIndex(1);
}

//*****************************//
//打开关闭串口按钮被按下槽函数
//*****************************//
void MainWindow::on_AN_FNComProt_clicked()
{
  if(ui->AN_FNComProt->text()==tr("打开串口"))
  {


    //设置串口名字
    m_serialPort.setPortName(ui->XLK_ComName->currentText());
    //设置波特率
    m_serialPort.setBaudRate(ui->XLK_BaudRate->currentText().toInt());
    //设置数据位
    m_serialPort.setDataBits(QSerialPort::Data8);
    //设置奇偶校验位
    m_serialPort.setParity(QSerialPort::NoParity);
    //设置停止位
    m_serialPort.setStopBits(QSerialPort::OneStop);
    //设置流控
    m_serialPort.setFlowControl(QSerialPort::NoFlowControl);
    if (m_serialPort.open(QIODevice::ReadWrite))
      {
        ui->AN_FNComProt->setText(tr("关闭串口"));
        ui->AN_Send->setEnabled(true);
        ui->AN_SendFile->setEnabled(true);
        ui->AN_SendItem->setEnabled(true);
        ui->AN_SendArray->setEnabled(true);
        ui->AN_StopSend->setEnabled(true);
        ui->XZK_TimerSend->setEnabled(true);
        this->setWindowTitle(tr("串口已打开"));
      }
  }else{
    ui->AN_FNComProt->setText(tr("打开串口"));
    ui->AN_Send->setEnabled(false);
    ui->AN_SendFile->setEnabled(false);
    ui->AN_SendItem->setEnabled(false);
    ui->AN_SendArray->setEnabled(false);
    ui->AN_StopSend->setEnabled(false);
    ui->XZK_TimerSend->setEnabled(false);
    this->setWindowTitle(tr("串口已关闭"));
    m_serialPort.close();
  }
}

//*****************************//
//接收到串口发来的信息的槽函数
//*****************************//
void MainWindow::readData()
{

  QByteArray Data=m_serialPort.readAll();

  if (!Data.isEmpty())
  {

    RXD_count++;
    if(RXD_count%1==0)
      ui->LED_RXD->setChecked(1);
    ui->LED_RXD->setText("RXD:"+QString::number(RXD_count));
    QString str = ui->BJK_Rece->toPlainText();
    QString data="";
    //Hex接收转换
    if(ui->XZK_HEXRece->checkState()==Qt::Checked)
    {
      QString hex = Data.toHex();
      ui->XZK_ShowTime->setCheckState(Qt::Unchecked);
      for(int i=0;i<Data.length();i+=2)
      {
        data+=hex.mid(i, 2).toUpper() + " ";
      }
    }else{
      data += tr(Data);
    }

    //时间戳增加
    if(ui->XZK_ShowTime->checkState()==Qt::Checked)
    {
      QTime current_time =QTime::currentTime();
      QString Time="@"+QString::number(current_time.hour())+":"+QString::number(current_time.minute())+":"+QString::number(current_time.second())+":"+QString::number(current_time.msec())+"<===::";
      str+=Time+data;
    }else{
      str+="@<===::"+data;
    }
    ui->BJK_Rece->clear();
    ui->BJK_Rece->append(str+"\n");
    if(RXD_count%2==0)
      ui->LED_RXD->setChecked(0);

  }
}

//*****************************//
//设置串口号被更改,串口名也跟着更改
//*****************************//
void MainWindow::on_XLK_ComName_activated(int index)
{
    ui->XLK_ComPort->setCurrentIndex(index);
}

//*****************************//
//设置串口名被更改,串口号也跟着更改
//*****************************//
void MainWindow::on_XLK_ComPort_activated(int index)
{
    ui->XLK_ComName->setCurrentIndex(index);
}

//*****************************//
//清空接收区内容
//*****************************//
void MainWindow::on_AN_ClearRece_clicked()
{
  ui->BJK_Rece->clear();
}

//*****************************//
//清空发送区内容
//*****************************//
void MainWindow::on_AN_ClearSend_clicked()
{
  ui->BJK_Send->clear();
}

//*****************************//
//双字节转char 转 HEX
//*****************************//
char ConvertHexChar(char ch)
{
    if((ch>='0') && (ch<='9'))
        return ch-0x30;
    else if((ch>='A') && (ch<='F'))
        return ch-'A'+10;
    else if((ch>='a') && (ch<='f'))
        return ch-'a'+10;
    else{
        return (-1);
    }
}

//*****************************//
//HEX形式的字符串转HEX数组
//*****************************//
QByteArray QString2Hex(QString str)
{
    QByteArray senddata;
    int hexdata,lowhexdata;
    int hexdatalen = 0;
    int len = str.length();
    senddata.resize(len/2);
    char lstr,hstr;
    for (int i=0; i<len;)
    {
        hstr = str[i].toLatin1();
        if (hstr == ' ')
        {
            i++;
            continue;
        }
        i++;
        if (i >=len)
            break;
        lstr = str[i].toLatin1();
        hexdata = ConvertHexChar(hstr);
        lowhexdata = ConvertHexChar(lstr);
        if((hexdata==16) || (lowhexdata==16))
        {
            break;
        }else{
            hexdata = hexdata*16+lowhexdata;
        }
        i++;
        senddata[hexdatalen] = (char)hexdata;
        hexdatalen++;
    }
    senddata.resize(hexdatalen);
    return senddata;
}

//*****************************//
//串口发送函数
//*****************************//
void MainWindow::SendData(QByteArray data)
{
  this->setWindowTitle(tr("串口已打开!正在发送....."));
  if(isSend)
  {
    QString str = ui->BJK_Rece->toPlainText();
    str+="@===>"+data+"\n";
    ui->BJK_Rece->clear();
    ui->BJK_Rece->append(str);
    TXD_count++;
    if(RXD_count%1==0)
      ui->LED_TXD->setChecked(1);
    ui->LED_TXD->setText("TXD:"+QString::number(TXD_count));
    if(ui->XZK_HEXSend->checkState()==Qt::Checked)
    {
      //qDebug()<<QString2Hex(data.toLatin1());
      m_serialPort.write(QString2Hex(data));
    }else{
      m_serialPort.write(data);
    }
    if(RXD_count%2==0)
      ui->LED_TXD->setChecked(0);

  }
  this->setWindowTitle(tr("串口已打开!未开始发送....."));
}

//*****************************//
//发送按钮被按下槽函数
//*****************************//
void MainWindow::on_AN_Send_clicked()
{
  isSend=true;
  if(ui->XZK_EditBelow->checkState()==Qt::Checked)
  {
    SendData(ui->BJK_SendItem->toPlainText().toLatin1());
  }else{
    SendData(ui->BJK_Send->toPlainText().toLatin1());
  }

}

//*****************************//
//发送数组按钮被按下槽函数
//*****************************//
void MainWindow::on_AN_SendArray_clicked()
{
  isSend=true;
  QString Senddata;
  if(ui->XZK_EditBelow->checkState()==Qt::Checked)
  {
    Senddata=ui->BJK_SendItem->toPlainText();
  }else{
    Senddata=ui->BJK_Send->toPlainText();
  }
  QStringList DataList = Senddata.split(",");
  ui->JDT->setMaximum(DataList.length());
  ui->JDT->setValue(0);
  for(int i=0;i<DataList.length();i++)
  {
      SendData(DataList[i].toLatin1());
      Delay(ui->BJK_Delay->value());
      ui->JDT->setValue(i);
  }
  ui->JDT->setValue(DataList.length());
}

//*****************************//
//HEX发送 选择框 被单击槽函数
//*****************************//
void MainWindow::on_XZK_HEXSend_clicked(bool checked)
{
  if(ui->XZK_EditBelow->checkState()==Qt::Checked)
    Hex_BiaoZhi=0;
  if(checked && Hex_BiaoZhi==0)
  {
    QString Str=ui->BJK_Send->toPlainText();
    QByteArray Hex=Str.toLatin1().toHex();
    Str.clear();
    for(int i=0;i<Hex.length();i+=2)
    {
      Str+=Hex.mid(i, 2).toUpper() + " ";
    }

    ui->BJK_Send->setText(Str);
    Hex_BiaoZhi=1;
    take=ui->BJK_Send->toPlainText();
  }
}

//*****************************//
//扫定时器超时槽函数
//*****************************//
void MainWindow::handleTimeout()
{
  //qDebug()<<"到达定时器一次\n";
  if(!isSend)
    m_pTimer->stop();
  else{
    m_pTimer->start(ui->BJK_Timer->value());
    on_AN_Send_clicked();
  }

}

//*****************************//
//停止发送按钮被按下槽函数
//*****************************//
void MainWindow::on_AN_StopSend_clicked()
{
  isSend=false;
  ui->XZK_TimerSend->setChecked(false);
}

//*****************************//
//定时发送选择框被单击槽函数
//*****************************//
void MainWindow::on_XZK_TimerSend_clicked(bool checked)
{
    if(checked && isSend)
    {
      m_pTimer->start(ui->BJK_Timer->value());
      isSend=true;
    }else{
      m_pTimer->stop();
    }
}

//*****************************//
//逐行发送按钮被按下槽函数
//*****************************//
void MainWindow::on_AN_SendItem_clicked()
{
  isSend=true;
  QString Senddata;
  if(ui->XZK_EditBelow->checkState()==Qt::Checked)
  {
    Senddata=ui->BJK_SendItem->toPlainText();
  }else{
    Senddata=ui->BJK_Send->toPlainText();
  }
  QStringList DataList = Senddata.split("\n");
  qDebug()<<DataList;
  ui->JDT->setMaximum(DataList.length());
  ui->JDT->setValue(0);
  for(int i=0;i<DataList.length();i++)
  {
      SendData(DataList[i].toLatin1());
      Delay(ui->BJK_Delay->value());
      ui->JDT->setValue(i);
  }
  ui->JDT->setValue(DataList.length());
}

//*****************************//
//打开文件按钮被按下槽函数
//*****************************//
void MainWindow::on_AN_OpenFile_clicked()
{

  //选择单个文件
  QString curPath=QDir::currentPath();//获取系统当前目录
  //获取应用程序的路径
  QString dlgTitle="选择要发送的文件"; //对话框标题
  QString filter="文本文件(*.txt);;C语言文件(*.c *.cpp *.h);;所有文件(*.*)"; //文件过滤器
  QString aFileName=QFileDialog::getOpenFileName(this,dlgTitle,curPath,filter);
  if (!aFileName.isEmpty())
    ui->BJK_FilePath->setText(aFileName);
  QFile file(aFileName);
  if (!file.open(QIODevice::ReadOnly|QIODevice::Text))//打开指定文件
  {
    QMessageBox::about(NULL, "文件", "文件打开失败");
  }
  QTextStream txtInput(&file);
  QString lineStr;
  ui->BJK_Send->setText(txtInput.readAll());
}

//*****************************//
//发送文件按钮被按下槽函数
//*****************************//
void MainWindow::on_AN_SendFile_clicked()
{
  isSend=true;
  SendData(ui->BJK_Send->toPlainText().toLatin1());
}

//*****************************//
//清空发送计数按钮被按下槽函数
//*****************************//
void MainWindow::on_AN_ClearSendCount_clicked()
{
  TXD_count=0;
  ui->LED_TXD->setText("TXD:"+QString::number(TXD_count));
}

//*****************************//
//清空接收计数按钮被按下槽函数
//*****************************//
void MainWindow::on_AN_ClearReceCount_clicked()
{
  RXD_count=0;
  ui->LED_RXD->setText("RXD:"+QString::number(RXD_count));
}
